package com.truyen.persistence.dao.base;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import com.truyen.utils.PagingInfo;

/**
 * @author quanhm
 * @param <T>
 *            Entity
 * @param <ID>
 *            Wrapper type of ID
 */
public interface GenericJpaBaseDao<T, ID extends Serializable> {
	/**
	 * Get the Class of the entity.
	 * 
	 * @return the class
	 */
	Class<T> getEntityClass();

	/**
	 * Find an entity by its primary key
	 * 
	 * @param id
	 *            the primary key
	 * @return the entity
	 */
	T findById(final ID id);

	/**
	 * Load all entities.
	 * 
	 * @return the list of entities
	 */
	List<T> findAll();

	/**
	 * Load all entities.
	 * 
	 * @param pInfo
	 *            information of paging
	 * @return the list of entities
	 */
	List<T> findAll(PagingInfo pInfo);

	/**
	 * @param query
	 *            string
	 * @param values
	 *            parameters
	 * @return List of entity
	 */
	List<T> findByQuery(String query, Object... values);

	/**
	 * Find using a named query.
	 * 
	 * @param queryName
	 *            the name of the query
	 * @param params
	 *            the query parameters
	 * 
	 * @return the list of entities
	 */
	List<T> findByNamedQuery(final String queryName, Object... params);

	/**
	 * Find using a named query.
	 * 
	 * @param queryName
	 *            the name of the query
	 * @param params
	 *            the query parameters
	 * 
	 * @return the list of entities
	 */
	List<T> findByNamedQueryAndNamedParams(final String queryName,
			final Map<String, ? extends Object> params);

	/**
	 * @param q
	 *            query body
	 * @param pInfo
	 *            information of paging
	 * @return
	 */
	List<T> findWithPaging(String q, PagingInfo pInfo);

	/**
	 * find by a property
	 * 
	 * @param property
	 *            name of property
	 * @param value
	 *            compared value
	 * @return List of entity
	 */
	List<T> findByProperty(String property, Object value);

	/**
	 * @param property
	 * @param value
	 * @param maxLimit
	 * @return
	 */
	List<T> findByPropertyLimit(String property, Object value, int maxLimit);

	/**
	 * find by property with paging info (total page will be set for pInfo)
	 * 
	 * @param property
	 * @param value
	 * @param pInfo
	 *            paging info
	 * @return result list
	 */
	List<T> findByProperty(String property, Object value, PagingInfo pInfo);

	/**
	 * find a list of properties
	 * 
	 * @param propertiesMap
	 *            dictionary of key/value pair (propertyName/value)
	 * @return List of entity
	 */
	List<T> findByProperties(Map<String, Object> propertiesMap);

	/**
	 * find a list of properties with paging info (total page will be set for
	 * pInfo)
	 * 
	 * @param propertiesMap
	 * @param pInfo
	 * @return result list
	 */
	List<T> findByProperties(Map<String, Object> propertiesMap, PagingInfo pInfo);

	/**
	 * @param whereClauses
	 *            where phrase
	 * @return number of all items according to condition
	 */
	long countByWhere(String whereClauses);

	/**
	 * @param whereClauses
	 * @param sizeInPage
	 * @return total page according to WHERE clauses in size per page
	 */
	int countTotalPage(String whereClauses, int sizeInPage);

	/**
	 * Count all entities.
	 * 
	 * @return the number of entities
	 */
	long countAll();

	/**
	 * @param property
	 * @param value
	 * @return count according to property filter
	 */
	int countByProperty(String property, Object value);

	/**
	 * @param propertiesMap
	 * @param pInfo
	 * @return count according to properties filter
	 */
	int countByProperties(Map<String, Object> propertiesMap, PagingInfo pInfo);

	/**
	 * @param criteriaQuery
	 * @param entity
	 * @return number of rows of criteriaQuery and entity
	 */
	long countByQuery(CriteriaQuery<T> criteriaQuery, Root<T> entity);

	/**
	 * save an entity. This can be a INSERT or UPDATE in the database.
	 * 
	 * @param entity
	 *            the entity to save
	 * 
	 * @return the saved entity
	 */
	void save(final T entity);

	/**
	 * Merge an entity to current entity manager
	 * 
	 * @param Entity
	 */
	void merge(T entity);

	/**
	 * Permanently Remove an entity from the database.
	 * 
	 * @param entity
	 *            the entity to delete
	 */
	void delete(final T entity);
	
	/**
	 * 
	 * @param property
	 * @param value
	 * @return
	 */

	List<T> findByPropertyNotNull(String property);

}
